﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using Dapper;
using SystemSettings;
using Labthink.PCSoft.UniversalHost4.Model;
using Labthink.PCSoft.UniversalHost4.Model.Flow;
using Labthink.PCSoft.UniversalHost4.Model.Setting;
using Labthink.PCSoft.UniversalHost4.Model.Unit;
using Labthink.PCSoft.UniversalHost4.Utility;
using NLog;
using FullData = Labthink.PCSoft.UniversalHost4.Model.FullData;

namespace Labthink.PCSoft.UniversalHost4.DataAccess
{
    public class CurrentRepository : BaseRepository
    {
        private static Dictionary<int, Note> _unitConversion;//单位转换关系
        private static Dictionary<string, Note> _unitConversionSupply;//单位转换关系
        private static DataTable _dtAllConversions;
        public static string AppPath = AppDomain.CurrentDomain.BaseDirectory;
        private static readonly string DatabaseBasePath = Path.Combine(AppPath, @"Config");
        private static string _databasePath = Path.Combine(DatabaseBasePath, @"Default");//当前数据库模板目录
        private static Dictionary<int, List<FullData>> _paramTemps; //参数模板
        private static Dictionary<int, List<FullData>> _resultTemps;//结果模板
        private static Dictionary<int, List<FullData>> _dataTemps; //数据模板
        private static Dictionary<int, DataTable> _dtParamTemps;
        private static Dictionary<int, DataTable> _dtResultTemps;//结果模板
        private static Dictionary<int, DataTable> _dtDataTemps; //数据模板
        private static Dictionary<string, string> _languageZh;
        private static Dictionary<string, string> _languageEn;
        private const string CreateConversion = "CREATE TABLE [Note] ([UnitCode] VARCHAR(255),[DataNo] INT, [PrecisionTo] VARCHAR(255), [UnitTo] VARCHAR(255), [KValue] DOUBLE, [BValue] DOUBLE,[IsDefault] BOOL)";
        private static bool _realTimeSave;//是否实时保存数据
        private static int _saveCount;//数据保存条数
        public static string Unit;
        private static string _language;

        public static int TypeNo = 10033;

        private static readonly Logger Log = LogManager.GetCurrentClassLogger();
        private static Dictionary<int, MemoryDatabase> _databases;//内存数据集合

        /// <summary>
        /// 加载指定的单位转换关系
        /// </summary>
        public static void Load()
        {
            var unit = HasMultipleUnits();
            Unit = unit;
            if (string.IsNullOrEmpty(unit))
            {
                _unitConversion = null;
                _unitConversionSupply = null;
                _dtAllConversions = null;
            }
            else
            {
                _databasePath = Path.Combine(AppPath, @"Config", unit);
                var unitPath = Path.Combine(DatabaseBasePath, unit + "\\Unit.note");
                if (File.Exists(unitPath))
                {
                    if (_unitConversion == null)
                    {
                        _unitConversion = new Dictionary<int, Note>();
                    }

                    if (_unitConversionSupply == null)
                    {
                        _unitConversionSupply = new Dictionary<string, Note>();
                    }

                    _unitConversion.Clear();
                    _unitConversionSupply.Clear();
                    Log.Debug("加载单位{0}的转换关系", unit);
                    const string sql = "SELECT * FROM Note";
                    var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(unitPath));
                    con.Open();
                    using SQLiteCommand cmd = con.CreateCommand();
                    try
                    {
                        var reader = SqliteHelper.ExecuteReader(cmd, sql, null);
                        while (reader.Read())
                        {
                            var note = new Note
                            {
                                DataNo = reader["DataNo"].ToInt32(),
                                PrecisionTo = reader["PrecisionTo"].ToInt32(),
                                UnitTo = reader["UnitTo"].ToString(),
                                UnitFrom = reader["UnitFrom"].ToString(),
                                BValue = reader["BValue"].ToDouble(),
                                KValue = reader["KValue"].ToDouble()
                            };
                            _unitConversion.Add(note.DataNo, note);
                            if (!_unitConversionSupply.ContainsKey(note.UnitFrom))
                            {
                                _unitConversionSupply.Add(note.UnitFrom, note);
                            }
                        }
                        reader.Close();
                    }
                    catch (Exception e)
                    {
                        Log.Error("加载{0}的单位转换关系失败", e, unit);
                    }
                }
                else
                {
                    Log.Debug("多单位:没有找到单位{0}对应的单位转换配置文件{1}", unit, unitPath);
                }
            }

            //加载模板
            LoadTemplate();
            _databases ??= new Dictionary<int, MemoryDatabase>();
            _realTimeSave = IniHelper.GetIni(IniFile, "base", "realTimeSave", "0") != "0";
            _saveCount = IniHelper.GetIni(IniFile, "base", "saveCount", "1000").ToInt32();
            //自定义查询条件
            CreateSelfQuery();
        }

        public static string GetLanguage(int dataNo)
        {
            var lanId = "";
            foreach (var kvs in _paramTemps)
            {
                var fd = kvs.Value.SingleOrDefault(d => d.DataNo == dataNo);
                if (fd != null)
                {
                    lanId = fd.LanguageId;
                    break;
                }
            }

            if (lanId == "") return dataNo + "";
            return GetLanguage(lanId);
        }

        public static void PackParamForTrace(ParamForTrace pt)
        {
            var lanId = "";
            foreach (var kvs in _paramTemps)
            {
                FullData fd = kvs.Value.SingleOrDefault(d => d.DataNo == pt.DataNo);
                if (fd != null)
                {
                    lanId = fd.LanguageId;
                    pt.ColName = fd.ColumnName;
                    if (!string.IsNullOrEmpty(fd.Unit))
                        pt.Name = "(" + fd.Unit + ")";
                    break;
                }
            }

            if (lanId == "") pt.Name = pt.ColName + pt.Name;
            pt.Name = GetLanguage(lanId) + pt.Name;
        }

        /// <summary>
        /// 单位转换 根据数据编号进行转换
        /// 适用于参数、实时数据和结果
        /// </summary>
        /// <param name="datas"></param>
        public static void Conversion(List<FullData> datas)
        {
            if (_unitConversion == null || !_unitConversion.Any()) return;
            foreach (var data in datas)
            {
                if (data.ToString() == "-1") continue;
                if (data.DataType != DataType.Double) continue;
                if (_unitConversion.ContainsKey(data.DataNo))
                {
                    var c = _unitConversion[data.DataNo];
                    var t = data.Value;
                    data.Value = data.Value.ToDouble() * c.KValue + c.BValue;
                    data.Precision = c.PrecisionTo;
                    data.Unit = c.UnitTo;
                    Log.Trace("转换{0}，转换前{1}，转换后{2}", data.DataNo, t, data.Value);
                }
            }
        }

        /// <summary>
        /// 单位转换 根据标准单位进行转换
        /// </summary>
        /// <param name="datas"></param>
        public static void ConversionSupply(List<FullData> datas)
        {
            if (_unitConversionSupply == null || !_unitConversionSupply.Any()) return;
            foreach (var data in datas)
            {
                if (data.ToString() == "-1") continue;
                if (data.DataType != DataType.Double) continue;
                if (_unitConversionSupply.ContainsKey(data.Unit))
                {
                    var c = _unitConversionSupply[data.Unit];
                    var t = data.Value;
                    data.Value = data.Value.ToDouble() * c.KValue + c.BValue;
                    data.Precision = c.PrecisionTo;
                    data.Unit = c.UnitTo;
                    Log.Trace("转换{0}，转换前{1}，转换后{2}", data.DataNo, t, data.Value);
                }
            }
        }

        /// <summary>
        /// 单位转换 根据标准单位进行转换
        /// 适用于环境数据、标定数据等
        /// </summary>
        /// <param name="datas"></param>
        public static void ConversionSupply(List<SimplifyData> datas)
        {
            if (_unitConversionSupply == null || !_unitConversionSupply.Any()) return;
            foreach (var data in datas)
            {
                if (data.ToString() == "-1") continue;
                if (_unitConversionSupply.ContainsKey(data.Unit))
                {
                    var c = _unitConversionSupply[data.Unit];
                    var t = data.Value;
                    data.Value = data.Value.ToDouble() * c.KValue + c.BValue;
                    data.Value = data.Value.Round(c.PrecisionTo).ToDouble();
                    data.Unit = c.UnitTo;
                    Log.Trace("转换{0}，转换前{1}，转换后{2}", data.Unit, t, data.Value);
                }
            }
        }

        /// <summary>
        /// 根据试验类型获取参数结构
        /// </summary>
        /// <param name="testType"></param>
        /// <returns></returns>
        public static List<FullData> ParamInfo(int testType)
        {
            if (_paramTemps.ContainsKey(testType))
                return _paramTemps[testType].Clone();

            return null;
        }

        /// <summary>
        /// 根据试验类型获取参数结构
        /// </summary>
        /// <param name="dbKey"></param>
        /// <param name="testType"></param>
        /// <returns></returns>
        public static List<FullData> ParamInfo(string dbKey, int testType)
        {
            var dir = Path.Combine(DatabaseBasePath + "\\" + Unit, dbKey);
            var file = Path.Combine(dir, $"dbtemplate_{testType}.lt");
            if (!File.Exists(file)) return null;
            var info = new List<FullData>();
            using (var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(file)))
            {
                var cmd = con.CreateCommand();
                con.Open();
                //参数
                var reader = SqliteHelper.ExecuteReader(cmd, "SELECT * FROM TBL_ParamInfo", null);

                while (reader.Read())
                {
                    info.Add(new FullData
                    {
                        DataNo = reader["DataNo"].ToInt32(),
                        ColumnName = reader["ColumnName"].ToString(),
                        DataType = (DataType)reader["DataTypeId"].ToInt32(),
                        LanguageId = reader["LanguageId"].ToString(),
                        Precision = reader["Precision"].ToInt32(),
                        Unit = reader["Unit"].ToString(),
                        Text = GetLanguage(reader["LanguageId"].ToString())
                    });
                }

                reader.Close();
                cmd.Dispose();
            }

            return info;
        }

        /// <summary>
        /// 获取数据结构
        /// </summary>
        /// <param name="testType"></param>
        /// <returns></returns>
        public static List<FullData> DataInfo(int testType)
        {
            if (_dataTemps.ContainsKey(testType))
                return _dataTemps[testType].Clone();

            return null;
        }

        /// <summary>
        /// 获取数据结构
        /// </summary>
        /// <param name="dbKey"></param>
        /// <param name="testType"></param>
        /// <returns></returns>
        public static List<FullData> DataInfo(string dbKey, int testType)
        {
            var dir = Path.Combine(DatabaseBasePath + "\\" + Unit, dbKey);
            var file = Path.Combine(dir, $"dbtemplate_{testType}.lt");
            if (!File.Exists(file)) return null;
            var info = new List<FullData>();
            using (var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(file)))
            {
                var cmd = con.CreateCommand();
                con.Open();
                //参数
                var reader = SqliteHelper.ExecuteReader(cmd, "SELECT * FROM TBL_RealtimeDataInfo", null);

                while (reader.Read())
                {
                    info.Add(new FullData
                    {
                        DataNo = reader["DataNo"].ToInt32(),
                        ColumnName = reader["ColumnName"].ToString(),
                        DataType = (DataType)reader["DataTypeId"].ToInt32(),
                        LanguageId = reader["LanguageId"].ToString(),
                        Precision = reader["Precision"].ToInt32(),
                        Unit = reader["Unit"].ToString(),
                        Text = GetLanguage(reader["LanguageId"].ToString())
                    });
                }

                reader.Close();
                cmd.Dispose();
            }

            return info;
        }

        /// <summary>
        /// 获取结果结构
        /// </summary>
        /// <param name="testType"></param>
        /// <returns></returns>
        public static List<FullData> ResultInfo(int testType)
        {
            if (_resultTemps.ContainsKey(testType))
                return _resultTemps[testType].Clone();

            return null;
        }

        /// <summary>
        /// 获取结果结构
        /// </summary>
        /// <param name="dbKey"></param>
        /// <param name="testType"></param>
        /// <returns></returns>
        public static List<FullData> ResultInfo(string dbKey, int testType)
        {
            var dir = Path.Combine(DatabaseBasePath + "\\" + Unit, dbKey);
            var file = Path.Combine(dir, $"dbtemplate_{testType}.lt");
            if (!File.Exists(file)) return null;
            var info = new List<FullData>();
            using var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(file));
            var cmd = con.CreateCommand();
            con.Open();
            //参数
            var reader = SqliteHelper.ExecuteReader(cmd, "SELECT * FROM TBL_ResultInfo", null);

            while (reader.Read())
            {
                info.Add(new FullData
                {
                    DataNo = reader["DataNo"].ToInt32(),
                    ColumnName = reader["ColumnName"].ToString(),
                    DataType = (DataType)reader["DataTypeId"].ToInt32(),
                    LanguageId = reader["LanguageId"].ToString(),
                    Precision = reader["Precision"].ToInt32(),
                    Unit = reader["Unit"].ToString(),
                    Text = GetLanguage(reader["LanguageId"].ToString())
                });
            }

            reader.Close();
            cmd.Dispose();

            return info;
        }

        public static List<int> GetTempCount()
        {
            return _paramTemps.Keys.ToList();
        }

        public static Dictionary<int, string> GetAllTestType()
        {
            var fd = _paramTemps[1].SingleOrDefault(d => d.DataNo == TypeNo);
            if (fd == null) return null;
            List<string> keys;
            if (_language == "ZH")
                keys = _languageZh.Keys.Where(l => l.Contains(fd.LanguageId) && l != fd.LanguageId).ToList();
            else keys = _languageEn.Keys.Where(l => l.Contains(fd.LanguageId) && l != fd.LanguageId).ToList();
            var dic = new Dictionary<int, string>();
            foreach (var key in keys)
            {
                string lan;
                if (_language == "ZH")
                    lan = _languageZh[key];
                else lan = _languageEn[key];
                dic.Add(key.Replace(fd.LanguageId, "").ToInt32(), lan);
            }
            return dic;
        }

        public static string GetDbTemplate(string unit)
        {
            var file = Path.Combine(DatabaseBasePath, unit + ".zip");
            if (File.Exists(file)) return file;
            var dir = Path.Combine(DatabaseBasePath, unit);
            ZipTool.ZipDir(dir, file, "");
            return file;
        }

        /*
        #endregion

        #region Test

        /// <summary>
        /// 开始试验
        /// </summary>
        /// <param name="hasSub"></param>
        /// <param name="data">参数</param>
        /// <param name="start"></param>
        /// <param name="sn"></param>
        /// <returns></returns>
        public static int StartTest(int hasSub, DataBar data, DateTime start, string sn)
        {
            return StartTest(hasSub, data, start, sn, string.Empty);
        }

        /// <summary>
        /// 开始试验
        /// </summary>
        /// <param name="hasSub"></param>
        /// <param name="data">参数</param>
        /// <param name="start"></param>
        /// <param name="sn"></param>
        /// <param name="dbKey">数据库模标识，用于使用指定的数据库模板，dbkey作为文件名位于默认数据库路径下。比如dbkey=o2,则使用harddisk\bootstrap\config\temp\default\o2下的数据库模板</param>
        /// <returns></returns>
        public static int StartTest(int hasSub, DataBar data, DateTime start, string sn, string dbKey)
        {
            if (_databases.ContainsKey(data.DataSn)) return 0;
            Log.Debug("{0}开始试验，创建数据库", data.TestId);
            if (!_paramTemps.ContainsKey(data.TestType))
            {
                Log.Error("试验类型{0}的模板信息不存在", data.TestType);
                return -1;
            }

            var param = data.Datas.Clone();

            //创建内存数据库
            var md = new MemoryDatabase
            {
                CurrentCount = 0,
                RealtimeSave = _realtimesave,
                SaveCount = _saveCount,
                TestType = data.TestType,
                DatabaseName = sn + "-" + start.ToString("yyyyMMddHHmmss") + "_" + data.TestId,
                Datas = string.IsNullOrEmpty(dbKey) ? _dtDataTemps[data.TestType].Clone() : LoadDataTemp(dbKey, data.TestType),
                Results = string.IsNullOrEmpty(dbKey) ? _dtResultTemps[data.TestType].Clone() : LoadResultTemp(dbKey, data.TestType),
                LastOperateTime = DateTime.Now,
                Param = param,
                TagRemark = new TagAndRemark()
            };

            if (!string.IsNullOrEmpty(dbKey))
            {
                md.Params = LoadParamTemp(dbKey, data.TestType);
            }

            if (_realtimesave)
            {
                md.CurrentPath = DataFile + "\\" + GetAutoPath() + "\\" + md.DatabaseName;
                md.InitData();
            }
            else
            {
                md.CurrentPath = md.DatabaseName;
            }

            md.TestOverViews = new TestOverView
            {
                DefaultLanguageId = Language.LanguageId == "zh" ? 0 : 1,
                EquipmentSerialNo = Sn.ToInt32(),
                EquipmentType1 = Type,
                EquipmentType2 = Device,
                EquipmentYear = Year,
                IsSubTest = hasSub,
                TestId = data.TestId,
                TestStartTime = start,
                TestType = data.TestType
            };

            md.CellOrCup = data.DataSn;
            _databases.Add(data.DataSn, md);

            //复制数据库
            if (string.IsNullOrEmpty(dbKey))
            {
                File.Copy(_databasePath + "\\dbtemplate_" + data.TestType + ".lt", md.CurrentPath);
            }
            else
            {
                File.Copy(_databasePath + "\\" + dbKey + "\\dbtemplate_" + data.TestType + ".lt", md.CurrentPath);
            }


            //创建单位体系转换关系表
            //CreateUnitConversion(md.CurrentPath);

            //实时保存
            if (md.RealtimeSave)
            {
                md.TestOverViews.TestStopTime = md.TestOverViews.TestStartTime;
                var index = md.Save(_dtAllConversions, GetNameByTestType(param));
                if (index != null)
                {
                    var sq = new List<FullData>();
                    if (SelfQuery != null)
                    {
                        sq = SelfQuery.Clone();
                        foreach (var q in sq)
                        {
                            var fd = param.SingleOrDefault(d => d.DataNo == q.DataNo);
                            if (fd != null)
                            {
                                q.Value = fd.Value;
                            }
                        }
                    }

                    index.FilePath = md.CurrentPath;
                    HistoryRepository.SaveIndex(index, sq.ToArray());
                }

                return 1;
            }

            //添加消息队列
            MsgServer.SendMsg(101, data);
            return 1;
        }

        /// <summary>
        /// 更新参数信息
        /// </summary>
        /// <returns></returns>
        public static int UpdateParam(DataBar data)
        {
            if (data == null) throw new ArgumentNullException("data");
            int r;
            if (_databases == null) r = -1;
            else
            {
                var dataSub = data.DataSn;
                if (!_databases.ContainsKey(dataSub)) r = -1;
                else
                {
                    var db = _databases[dataSub];
                    Log.Debug("更新{0}的参数信息", db.DatabaseName);
                    r = db.UpdateParam(data.Datas.Clone());
                    if (db.RealtimeSave)
                    {
                        UpdateIndex(db.DatabaseName, null, null);
                    }
                }
            }

            //添加消息队列
            MsgServer.SendMsg(104, data);
            return r;
        }

        /// <summary>
        /// 添加一条实时数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static int AddData(DataBar data)
        {
            if (data == null) throw new ArgumentNullException("data");
            var r = 1;
            if (_databases == null) r = -1;
            else
            {
                var dataSub = data.DataSn;
                if (!_databases.ContainsKey(dataSub)) r = -1;
                else
                {
                    var db = _databases[dataSub];
                    Log.Debug("添加{0}的实时数据", db.DatabaseName);
                    db.AddData(data.Datas.Clone());
                    if (db.RealtimeSave)
                    {
                        UpdateIndex(db.DatabaseName, null, null);
                    }
                }
            }

            //添加消息队列
            MsgServer.SendMsg(105, data);
            return r;
        }

        public static int AddResult(DataBar data)
        {
            if (data == null) throw new ArgumentNullException("data");
            var r = 1;
            if (_databases == null) r = -1;
            else
            {
                var dataSub = data.DataSn;
                if (!_databases.ContainsKey(dataSub)) r = -1;
                else
                {
                    var db = _databases[dataSub];
                    Log.Debug("添加{0}的试验结果", db.DatabaseName);
                    db.AddResult(data.Datas.Clone());
                    if (db.RealtimeSave)
                    {
                        UpdateIndex(db.DatabaseName, null, null);
                    }
                }
            }

            //添加消息队列
            MsgServer.SendMsg(106, data);
            return r;
        }

        public static int DeleteSubTest(int dataSn, int subTestId)
        {
            if (!_databases.ContainsKey(dataSn)) return 0;
            var md = _databases[dataSn];

            return md.DeleteSubTest(subTestId);
        }

        /// <summary>
        /// 试验结束
        /// </summary>
        /// <param name="dataSn"></param>
        /// <returns></returns>
        public static int SaveTest(int dataSn)
        {
            if (!_databases.ContainsKey(dataSn)) return 0;
            var md = _databases[dataSn];
            Log.Debug("保存试验记录 {0}", md.TestOverViews.TestId);
            md.TestOverViews.TestStopTime = DateTime.Now;
            if (md.RealtimeSave)
            {
                UpdateIndex(md.DatabaseName, md.TestOverViews.TestStopTime, md.TagRemark);

                if (DataShieldClient.IsDataShield)
                {
                    DataShieldClient.AddFile(md.CurrentPath);
                }
            }
            else
            {
                var param = md.Param;
                var index = md.Save(_dtAllConversions, GetNameByTestType(param));
                if (index != null)
                {
                    var sq = new List<FullData>();
                    if (SelfQuery != null)
                    {
                        sq = SelfQuery.Clone();
                        foreach (var q in sq)
                        {
                            var fd = param.SingleOrDefault(d => d.DataNo == q.DataNo);
                            if (fd != null)
                            {
                                q.Value = fd.Value;
                            }
                        }
                    }

                    md.CurrentPath = DataFile + "\\" + GetAutoPath() + "\\" + md.DatabaseName;
                    index.FilePath = md.CurrentPath;

                    //复制数据库
                    File.Move(md.DatabaseName, md.CurrentPath);
                    HistoryRepository.SaveIndex(index, sq.ToArray());

                    md.Dispose();
                    _databases.Remove(dataSn);

                    if (DataShieldClient.IsDataShield)
                    {
                        DataShieldClient.AddFile(index.FilePath);
                    }
                }
                else
                {
                    return -1;
                }
            }

            MsgServer.SendMsg(102);
            return 1;
        }

        /// <summary>
        /// 清除试验记录
        /// </summary>
        /// <param name="testId"></param>
        /// <returns></returns>
        public static int RemoveTest(int testId)
        {
            if (!_databases.ContainsKey(testId)) return 0;
            var md = _databases[testId];
            Log.Debug("清除试验记录 {0}", md.TestOverViews.TestId);
            try
            {
                File.Delete(md.CurrentPath);
                RemoveIndex(md.DatabaseName);
                md.Dispose();
                _databases.Remove(testId);
                return 1;
            }
            catch (Exception e)
            {
                Log.Error("清除试验记录 {0} 失败", e, testId);
                return -1;
            }
        }

        /// <summary>
        /// 改变参数结构描述信息
        /// 一定要在SaveTest之前使用
        /// 可调整数据：
        /// 单位（unit），为空时忽略
        /// 语言编号（Language），为空时忽略
        /// 精度（Precision），小于0忽略
        /// </summary>
        /// <param name="testType"></param>
        /// <param name="datas"></param>
        public static void ChangeParamStruct(int testType, List<FullData> datas)
        {
            foreach (var kvs in _databases)
            {
                if (kvs.Value.TestType == testType)
                {
                    kvs.Value.ChangeStruct(InfoType.Param, datas);
                }
            }
        }

        /// <summary>
        /// 改变数据结构描述信息
        /// 一定要在SaveTest之前使用
        /// 可调整数据：
        /// 单位（unit），为空时忽略
        /// 语言编号（Language），为空时忽略
        /// 精度（Precision），小于0忽略
        /// </summary>
        /// <param name="testType"></param>
        /// <param name="datas"></param>
        public static void ChangeDataStruct(int testType, List<FullData> datas)
        {
            foreach (var kvs in _databases)
            {
                if (kvs.Value.TestType == testType)
                {
                    kvs.Value.ChangeStruct(InfoType.Data, datas);
                }
            }
        }

        /// <summary>
        /// 改变结果结构描述信息
        /// 一定要在SaveTest之前使用
        /// 可调整数据：
        /// 单位（unit），为空时忽略
        /// 语言编号（Language），为空时忽略
        /// 精度（Precision），小于0忽略
        /// </summary>
        /// <param name="testType"></param>
        /// <param name="datas"></param>
        public static void ChangeResultStruct(int testType, List<FullData> datas)
        {
            foreach (var kvs in _databases)
            {
                if (kvs.Value.TestType == testType)
                {
                    kvs.Value.ChangeStruct(InfoType.Result, datas);
                }
            }
        }

        public static int UpdateTagAndRemark(TagAndRemark tr, string user)
        {
            if (tr.TestId > 0) return -1;
            var cn = Math.Abs(tr.TestId);
            if (!_databases.ContainsKey(cn)) return -1;
            if (user != _databases[cn].GetOpName()) return -403;
            _databases[cn].TagRemark = tr;
            return 1;
        }

        public static TagAndRemark GetTagAndRemark(int cn)
        {
            if (cn > 0) return null;
            try
            {
                var tmp = Math.Abs(cn);
                if (!_databases.ContainsKey(tmp)) return null;
                var tr = _databases[tmp].TagRemark;
                tr.TestId = cn;
                return tr;
            }
            catch (Exception e)
            {
                Log.Error("获取杯号{0}的标签或备注失败", e, -cn);
                return null;
            }
        }
        #endregion
        #endregion
        */
        #region private

        /// <summary>
        /// 创建自定义查询条件
        /// </summary>
        private static void CreateSelfQuery()
        {
            SelfQuery = new List<FullData>();
            var query = IniHelper.GetIni(IniFile, "self", "query", "");
            if (string.IsNullOrEmpty(query)) return;
            Log.Debug("发现自定义查询条件:{0}", query);
            var temp = _paramTemps[1];
            foreach (var str in query.Split(','))
            {
                var dno = str.ToInt32();
                if (dno == 0) continue;
                var fd = temp.SingleOrDefault(d => d.DataNo == dno);
                if (fd == null) continue;
                SelfQuery.Add((FullData)fd.Clone());
            }
        }

        /// <summary>
        /// 获取试验类型的名称
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private static string GetNameByTestType(IEnumerable<FullData> param)
        {
            var fd = param.SingleOrDefault(d => d.DataNo == 10034);
            if (fd == null) return string.Empty;
            var lanId = fd.LanguageId + fd.Value;
            if (_languageZh.ContainsKey(lanId))
                return _languageZh[lanId];
            return lanId;
        }

        /// <summary>
        /// 判断是否有多单位
        /// 加载所有单位转换关系
        /// </summary>
        /// <returns></returns>
        public static string HasMultipleUnits()
        {
            IsDbExist();
            Log.Debug("查找多单位");
            var sql = "SELECT COUNT(1) FROM Sqlite_master WHERE [type]='table' AND name='Units'";
            var o = SqliteHelper.ExecuteScalar(DbFile, sql, null);
            if (o == null || o.ToInt32() == 0)
            {
                Log.Debug("没有找到多单位");
                return string.Empty;
            }
            sql = "SELECT COUNT(1) FROM Units";
            o = SqliteHelper.ExecuteScalar(DbFile, sql, null);
            if (o == null || o.ToInt32() < 1)
            {
                Log.Debug("没有找到多单位");
                return string.Empty;
            }
            using (var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(DbFile)))
            {
                con.Open();
                o = SqliteHelper.ExecuteScalar(DbFile, "SELECT UnitCode FROM Units where isdefault=1");
                return o.ToString();
            }
        }

        /// <summary>
        /// 加载一种单位体系
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="unitPath"></param>
        /// <param name="isDefault"></param>
        private static void LoadOneUnit(string unit, string unitPath, bool isDefault)
        {
            Log.Debug("加载{0}的单位转换关系", unit);
            var sql = $"SELECT '{unit}' AS UnitCode,*,'{isDefault}' AS IsDefault FROM Note";

            if (_dtAllConversions == null)
            {
                _dtAllConversions = SqliteHelper.ExecuteDataSet(unitPath, sql, null).Tables[0];
            }
            else
            {
                _dtAllConversions.Merge(SqliteHelper.ExecuteDataSet(unitPath, sql, null).Tables[0]);
            }
        }

        /// <summary>
        /// 加载数据库模板
        /// </summary>
        private static void LoadTemplate()
        {
            Log.Debug("加载{0}中的数据库模板", _databasePath);
            if (_paramTemps == null)
            {
                _paramTemps = new Dictionary<int, List<FullData>>();
                _dtParamTemps = new Dictionary<int, DataTable>();
            }

            if (_resultTemps == null)
            {
                _resultTemps = new Dictionary<int, List<FullData>>();
                _dtResultTemps = new Dictionary<int, DataTable>();
            }

            if (_dataTemps == null)
            {
                _dataTemps = new Dictionary<int, List<FullData>>();
                _dtDataTemps = new Dictionary<int, DataTable>();
            }

            _paramTemps.Clear();
            _dtParamTemps.Clear();
            _resultTemps.Clear();
            _dtResultTemps.Clear();
            _dataTemps.Clear();
            _dtDataTemps.Clear();
            LoadLanguage();
            foreach (var file in Directory.GetFiles(_databasePath))
            {
                var fn = Path.GetFileName(file);
                if (string.IsNullOrEmpty(fn)) continue;
                if (!fn.StartsWith("dbtemplate")) continue;
                LoadOneTemplate(file);
            }
        }

        /// <summary>
        /// 加载数据库语言
        /// </summary>
        private static void LoadLanguage()
        {
            if (_languageZh == null)
            {
                _languageZh = new Dictionary<string, string>();
                _languageEn = new Dictionary<string, string>();
            }

            _languageZh.Clear();
            _languageEn.Clear();
            var file = Path.Combine(_databasePath, "dbtemplate_1.lt");
            if (!File.Exists(file))
            {
                Log.Error("加载数据库语言失败，没有找到文件{0}", file);
                return;
            }

            var sql = "SELECT LanguageId,ChineseText,EnglishText FROM TBL_Language";
            try
            {
                var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(file));
                con.Open();
                var cmd = con.CreateCommand();
                var reader = SqliteHelper.ExecuteReader(cmd, sql, null);
                while (reader.Read())
                {
                    _languageZh.Add(reader[0].ToString(), reader[1].ToString());
                    _languageEn.Add(reader[0].ToString(), reader[2].ToString());
                }
                reader.Close();
            }
            catch (Exception e)
            {
                Log.Error("加载数据库语言失败：{0}", e, sql);
            }
        }

        /// <summary>
        /// 根据语言编号获取语言
        /// </summary>
        /// <param name="lid"></param>
        /// <returns></returns>
        private static string GetLanguage(string lid)
        {
            var lan = SystemInfo.GetCurrentLocale().ToUpper();
            if (lan.Contains("CN"))
            {
                _language = "ZH";
                if (_languageZh.ContainsKey(lid)) return _languageZh[lid];
            }
            else
            {
                _language = "EN";
                if (_languageEn.ContainsKey(lid)) return _languageEn[lid];
            }

            Log.Error("没有找到{0}对应的语言", lid);
            return lid;
        }

        /// <summary>
        ///  加载一个数据模板的信息
        /// </summary>
        /// <param name="file"></param>
        private static void LoadOneTemplate(string file)
        {
            Log.Debug("加载{0}的数据模板", file);
            var fn = Path.GetFileNameWithoutExtension(file);
            if (string.IsNullOrEmpty(fn)) return;
            try
            {
                int tt = fn.Split('_')[1].ToInt32();
                var info = new List<FullData>();
                var con = new SQLiteConnection(SqliteHelper.CreateConnectionString(file));
                var cmd = con.CreateCommand();
                con.Open();
                //参数
                var reader = SqliteHelper.ExecuteReader(cmd, "SELECT * FROM TBL_ParamInfo", null);
                while (reader.Read())
                {
                    info.Add(new FullData
                    {
                        DataNo = reader["DataNo"].ToInt32(),
                        ColumnName = reader["ColumnName"].ToString(),
                        DataType = (DataType)reader["DataTypeId"].ToInt32(),
                        LanguageId = reader["LanguageId"].ToString(),
                        Precision = reader["Precision"].ToInt32(),
                        Unit = reader["Unit"].ToString(),
                        Text = GetLanguage(reader["LanguageId"].ToString())
                    });
                }

                reader.Close();
                cmd.Dispose();
                _paramTemps.Add(tt, info);

                //数据
                info = new List<FullData>();
                if (con.State != ConnectionState.Open) con.Open();
                cmd = con.CreateCommand();
                reader = SqliteHelper.ExecuteReader(cmd, "SELECT * FROM TBL_RealTimeDataInfo", null);
                while (reader.Read())
                {
                    info.Add(new FullData
                    {
                        DataNo = reader["DataNo"].ToInt32(),
                        ColumnName = reader["ColumnName"].ToString(),
                        DataType = (DataType)reader["DataTypeId"].ToInt32(),
                        LanguageId = reader["LanguageId"].ToString(),
                        Precision = reader["Precision"].ToInt32(),
                        Unit = reader["Unit"].ToString(),
                        Text = GetLanguage(reader["LanguageId"].ToString())
                    });
                }
                reader.Close();
                cmd.Dispose();
                _dataTemps.Add(tt, info);

                //结果
                info = new List<FullData>();
                if (con.State != ConnectionState.Open) con.Open();
                cmd = con.CreateCommand();
                reader = SqliteHelper.ExecuteReader(cmd, "SELECT * FROM TBL_ResultInfo", null);
                while (reader.Read())
                {
                    info.Add(new FullData
                    {
                        DataNo = reader["DataNo"].ToInt32(),
                        ColumnName = reader["ColumnName"].ToString(),
                        DataType = (DataType)reader["DataTypeId"].ToInt32(),
                        LanguageId = reader["LanguageId"].ToString(),
                        Precision = reader["Precision"].ToInt32(),
                        Unit = reader["Unit"].ToString(),
                        Text = GetLanguage(reader["LanguageId"].ToString())
                    });
                }
                reader.Close();
                cmd.Dispose();
                _resultTemps.Add(tt, info);

                //表结构
                var dt = SqliteHelper.ExecuteDataSet(file, "SELECT * FROM TBL_Param WHERE Id=-1", null).Tables[0];
                _dtParamTemps.Add(tt, dt);
                dt = SqliteHelper.ExecuteDataSet(file, "SELECT * FROM TBL_RealTimeData WHERE Id=-1", null).Tables[0];
                _dtDataTemps.Add(tt, dt);
                dt = SqliteHelper.ExecuteDataSet(file, "SELECT * FROM TBL_Result WHERE Id=-1", null).Tables[0];
                _dtResultTemps.Add(tt, dt);
            }
            catch (Exception e)
            {
                Log.Error("加载{0}的数据模板失败", e, file);
            }
        }

        /// <summary>
        /// 加载指定dbKey的模板
        /// </summary>
        /// <param name="dbKey"></param>
        /// <param name="testType"></param>
        /// <returns></returns>
        private static DataTable LoadDataTemp(string dbKey, int testType)
        {
            var dir = Path.Combine(DatabaseBasePath + "\\" + Unit, dbKey);
            var file = Path.Combine(dir, $"dbtemplate_{testType}.lt");
            if (!File.Exists(file)) return null;
            return SqliteHelper.ExecuteDataSet(file, "SELECT * FROM TBL_RealTimeData WHERE Id=-1", null).Tables[0];
        }

        private static DataTable LoadResultTemp(string dbKey, int testType)
        {
            var dir = Path.Combine(DatabaseBasePath + "\\" + Unit, dbKey);
            var file = Path.Combine(dir, $"dbtemplate_{testType}.lt");
            if (!File.Exists(file)) return null;
            return SqliteHelper.ExecuteDataSet(file, "SELECT * FROM TBL_Result WHERE Id=-1", null).Tables[0];
        }

        private static DataTable LoadParamTemp(string dbKey, int testType)
        {
            var dir = Path.Combine(DatabaseBasePath + "\\" + Unit, dbKey);
            var file = Path.Combine(dir, $"dbtemplate_{testType}.lt");
            if (!File.Exists(file)) return null;
            return SqliteHelper.ExecuteDataSet(file, "SELECT * FROM TBL_Param WHERE Id=-1", null).Tables[0];
        }

        /*
        /// <summary>
        /// 获取数据文件夹内的最大子文件夹值
        /// </summary>
        /// <returns></returns>
        private static int GetMaxPath()
        {
            var di = new DirectoryInfo(DataFile);
            var max = 1;
            foreach (DirectoryInfo dic in di.GetDirectories())
            {
                int tmp = Convert.ToInt32(dic.Name);
                if (tmp > max)
                {
                    max = tmp;
                }
            }
            return max;
        }

        /// <summary>
        /// 获取自动生成的数据文件夹编号
        /// </summary>
        /// <returns></returns>
        private static string GetAutoPath()
        {
            int maxPath = GetMaxPath();
            var path = Path.Combine(DataFile, maxPath + "");
            if (Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
                //return _NEWPath;
            }
            else
            {
                if (Directory.GetFiles(path).Length >= 900)
                {
                    maxPath = maxPath + 1;
                    Directory.CreateDirectory(Path.Combine(DataFile, maxPath + ""));
                }
            }
            //currentPath = maxPath + "";
            return maxPath + "";
        }
        */

        /// <summary>
        /// 为数据库文件创建单位关系转换表
        /// </summary>
        /// <param name="file"></param>
        private static void CreateUnitConversion(string file)
        {
            if (!ConfigAndSettings.GetBaseInfo().Unit) return;
            if (!File.Exists(file))
            {
                Log.Error("创建单位关系表时没找到文件{0}", file);
                return;
            }

            Log.Debug("创建{0}的单位转换关系表", file);
            try
            {
                SqliteHelper.ExecuteNonQuery(file, CreateConversion, null);
            }
            catch (Exception e)
            {
                Log.Error("创建{0}的单位转换关系表失败", e, file);
                throw;
            }
        }

        /// <summary>
        /// 更新索引信息
        /// </summary>
        /// <param name="name"></param>
        /// <param name="stop"></param>
        /// <param name="tr"></param>
        private static void UpdateIndex(string name, DateTime? stop, TagAndRemark tr)
        {
            IsDbExist();
            Log.Trace("更新{0}的索引信息", name);
            var sql = "UPDATE TestIndex SET EndTime=@EndTime {0} WHERE FileName=@FileName";
            var os = new List<object> { stop ?? DateTime.Now };
            if (tr != null)
            {
                sql = string.Format(sql, ",Tag=@Tag,Remark=@Remark");
                os.Add(tr.Tag);
                os.Add(tr.Remark);
                os.Add(name);
            }
            else
            {
                sql = string.Format(sql, " ");
                os.Add(name);
            }

            try
            {
                SqliteHelper.ExecuteNonQuery(DbFile, sql, os.ToArray());
            }
            catch (Exception e)
            {
                Log.Error("更新{0}的索引信息失败", e, name);
            }
        }

        /// <summary>
        /// 移除试验索引
        /// </summary>
        /// <param name="name"></param>
        private static void RemoveIndex(string name)
        {
            var sql = "DELETE FROM TestIndex  WHERE FileName=@FileName";
            SqliteHelper.ExecuteNonQuery(DbFile, sql, new object[] { name });
        }

        #endregion

        /// <summary>
        /// 修改参数信息表相关字段为下位机当前单位
        /// </summary>
        /// <param name="currentUnit"></param>
        /// <param name="dataNos"></param>
        public static void UpdateParamInfoUnit(string currentUnit, int nDigitP, int dataNo)
        {
            var file = _databases[1].CurrentPath;
            //using (var conn = new SQLiteConnection($"Data Source={file};Version=3;"))
            //{
            //    conn.Execute(@"update tbl_paramInfo set unit=@Text where dataNo in @DataNos",
            //        new { currentUnit, DataNos = dataNos });
            //}
            SqliteHelper.ExecuteNonQuery(file, "update TBL_ParamInfo set unit=@Text, Precision=@Precision where dataNo=@DataNo", currentUnit, nDigitP, dataNo);
        }
        /// <summary>
        /// 修改实时数据信息表相关字段为下位机当前单位
        /// </summary>
        /// <param name="currentUnit"></param>
        /// <param name="dataNos"></param>
        public static void UpdateRtdInfoUnit(string currentUnit, int nDigitP, int dataNo)
        {
            var file = _databases[1].CurrentPath;
            //using (var conn = new SQLiteConnection($"Data Source={file};Version=3;"))
            //{
            //    //conn.Execute(@"update tbl_RealTimeDataInfo set unit=@Text where dataNo in @DataNos",
            //    //    new { currentUnit, DataNos = dataNos });
            //    conn.Execute(@"update tbl_RealTimeDataInfo set unit=@Text where dataNo in @DataNos",
            //        new { currentUnit, dataNos });
            //}
            SqliteHelper.ExecuteNonQuery(file, "update tbl_RealTimeDataInfo set unit=@Text, Precision=@Precision where dataNo=@DataNo", currentUnit,nDigitP, dataNo);
        }

        /// <summary>
        /// 开始试验
        /// </summary>
        /// <param name="hasSub"></param>
        /// <param name="data">参数</param>
        /// <param name="start"></param>
        /// <param name="sn"></param>
        /// <returns></returns>
        public static int StartTest(int hasSub, DataBar data, DateTime start, string sn)
        {
            return StartTest(hasSub, data, start, sn, string.Empty);
        }

        /// <summary>
        /// 开始试验
        /// </summary>
        /// <param name="hasSub"></param>
        /// <param name="data">参数</param>
        /// <param name="start"></param>
        /// <param name="sn"></param>
        /// <param name="dbKey">数据库模标识，用于使用指定的数据库模板，dbkey作为文件名位于默认数据库路径下。比如dbkey=o2,则使用harddisk\bootstrap\config\temp\default\o2下的数据库模板</param>
        /// <returns></returns>
        public static int StartTest(int hasSub, DataBar data, DateTime start, string sn, string dbKey)
        {
            if (_databases.ContainsKey(data.DataSn)) return 0;
            Log.Debug("TestId={0},开始试验，创建数据库", data.TestId);
            if (!_paramTemps.ContainsKey(data.TestType))
            {
                Log.Error("试验类型{0}的模板信息不存在", data.TestType);
                return -1;
            }

            var param = data.Datas.Clone();

            //创建内存数据库
            var md = new MemoryDatabase
            {
                CurrentCount = 0,
                RealtimeSave = _realTimeSave,
                SaveCount = _saveCount,
                TestType = data.TestType,
                DatabaseName = sn + "-" + start.ToString("yyyyMMddHHmmss") + "_" + data.TestId + ".db",
                Datas = string.IsNullOrEmpty(dbKey) ? _dtDataTemps[data.TestType].Clone() : LoadDataTemp(dbKey, data.TestType),
                Results = string.IsNullOrEmpty(dbKey) ? _dtResultTemps[data.TestType].Clone() : LoadResultTemp(dbKey, data.TestType),
                LastOperateTime = DateTime.Now,
                Param = param,
                TagRemark = new TagAndRemark()
            };

            if (!string.IsNullOrEmpty(dbKey))
            {
                md.Params = LoadParamTemp(dbKey, data.TestType);
            }

            if (_realTimeSave)
            {
                md.CurrentPath = Path.Combine(DataFilePath, md.DatabaseName);
                md.InitData();
            }
            else
            {
                md.CurrentPath = Path.Combine(TempDir, md.DatabaseName);
            }

            md.TestOverViews = new TestOverView
            {
                DefaultLanguageId = 0,// zh
                EquipmentSerialNo = Sn.ToInt32(),
                EquipmentType1 = Type,
                EquipmentType2 = Device,
                EquipmentYear = Year,
                IsSubTest = hasSub,
                TestId = data.TestId,
                TestStartTime = start,
                TestType = data.TestType
            };

            md.CellOrCup = data.DataSn;
            _databases.Add(data.DataSn, md);

            //复制数据库
            if (string.IsNullOrEmpty(dbKey))
            {
                File.Copy(_databasePath + "\\dbtemplate_" + data.TestType + ".lt", md.CurrentPath);
            }
            else
            {
                File.Copy(_databasePath + "\\" + dbKey + "\\dbtemplate_" + data.TestType + ".lt", md.CurrentPath);
            }

            //创建单位体系转换关系表
            //CreateUnitConversion(md.CurrentPath);

            //实时保存
            if (md.RealtimeSave)
            {
                md.TestOverViews.TestStopTime = md.TestOverViews.TestStartTime;
                var index = md.Save(_dtAllConversions, GetNameByTestType(param));
                if (index != null)
                {
                    var sq = new List<FullData>();
                    if (SelfQuery != null)
                    {
                        sq = SelfQuery.Clone();
                        foreach (var q in sq)
                        {
                            var fd = param.SingleOrDefault(d => d.DataNo == q.DataNo);
                            if (fd != null)
                            {
                                q.Value = fd.Value;
                            }
                        }
                    }

                    index.FilePath = md.CurrentPath;
                    HistoryRepository.SaveIndex(index, sq.ToArray());
                }

                return 1;
            }

            return 1;
        }

        /// <summary>
        /// 试验结束
        /// </summary>
        /// <param name="dataSn"></param>
        /// <returns></returns>
        public static int SaveTest(int dataSn)
        {
            if (!_databases.ContainsKey(dataSn)) return 0;
            var md = _databases[dataSn];
            Log.Debug("保存试验记录 {0}", md.TestOverViews.TestId);
            md.TestOverViews.TestStopTime = DateTime.Now;
            md.TagRemark = new TagAndRemark();
            if (md.RealtimeSave)
            {
                UpdateIndex(md.DatabaseName, md.TestOverViews.TestStopTime, md.TagRemark);

                if (DataShieldClient.IsDataShield)
                {
                    DataShieldClient.AddFile(md.CurrentPath);
                }

                _databases.Remove(dataSn);
            }
            else
            {
                var param = md.Param;
                var index = md.Save(_dtAllConversions, GetNameByTestType(param));
                if (index != null)
                {
                    var sq = new List<FullData>();
                    if (SelfQuery != null)
                    {
                        sq = SelfQuery.Clone();
                        foreach (var q in sq)
                        {
                            var fd = param.SingleOrDefault(d => d.DataNo == q.DataNo);
                            if (fd != null)
                            {
                                q.Value = fd.Value;
                            }
                        }
                    }

                    md.CurrentPath = Path.Combine(DataFilePath, md.DatabaseName);
                    index.FilePath = md.CurrentPath;

                    //复制数据库
                    File.Move(md.DatabaseName, md.CurrentPath);
                    HistoryRepository.SaveIndex(index, sq.ToArray());

                    md.Dispose();
                    _databases.Remove(dataSn);

                    if (DataShieldClient.IsDataShield)
                    {
                        DataShieldClient.AddFile(index.FilePath);
                    }
                }
                else
                {
                    return -1;
                }
            }

            return 1;
        }

        /// <summary>
        /// 更新参数信息
        /// </summary>
        /// <returns></returns>
        public static int UpdateParam(DataBar data)
        {
            if (data == null) throw new ArgumentNullException(nameof(data));
            int r;
            if (_databases == null) r = -1;
            else
            {
                var dataSub = data.DataSn;
                if (!_databases.ContainsKey(dataSub)) r = -1;
                else
                {
                    var db = _databases[dataSub];
                    Log.Debug("更新{0}的参数信息", db.DatabaseName);
                    r = db.UpdateParam(data.Datas.Clone());
                    if (db.RealtimeSave)
                    {
                        UpdateIndex(db.DatabaseName, null, null);
                    }
                }
            }

            return r;
        }

        /// <summary>
        /// 清除试验记录
        /// </summary>
        /// <param name="testId"></param>
        /// <returns></returns>
        public static int RemoveTest(int testId)
        {
            if (!_databases.ContainsKey(testId)) return 0;
            var md = _databases[testId];
            Log.Debug("清除试验记录 {0}", md.TestOverViews.TestId);
            try
            {
                File.Delete(md.CurrentPath);
                RemoveIndex(md.DatabaseName);
                md.Dispose();
                _databases.Remove(testId);
                return 1;
            }
            catch (Exception e)
            {
                Log.Error("清除试验记录 {0} 失败", e, testId);
                return -1;
            }
        }

        /// <summary>
        /// 添加一条实时数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static int AddData(DataBar data)
        {
            if (data == null) throw new ArgumentNullException(nameof(data));
            var r = 1;
            if (_databases == null) r = -1;
            else
            {
                var dataSub = data.DataSn;
                if (!_databases.ContainsKey(dataSub)) r = -1;
                else
                {
                    var db = _databases[dataSub];
                    Log.Trace("添加{0}的实时数据", db.DatabaseName);
                    db.AddData(data.Datas.Clone());
                    if (db.RealtimeSave)
                    {
                        UpdateIndex(db.DatabaseName, null, null);
                    }
                }
            }

            return r;
        }

        public static int AddResult(DataBar data)
        {
            if (data == null) throw new ArgumentNullException(nameof(data));
            var r = 1;
            if (_databases == null) r = -1;
            else
            {
                var dataSub = data.DataSn;
                if (!_databases.ContainsKey(dataSub)) r = -1;
                else
                {
                    var db = _databases[dataSub];
                    db.AddResult(data.Datas.Clone());
                    if (db.RealtimeSave)
                    {
                        UpdateIndex(db.DatabaseName, null, null);
                    }
                }
            }

            return r;
        }
    }
}
